package com.example.hotHub.service.impl;


import com.example.hotHub.cnst.CommonConst;
import com.example.hotHub.model.NormalHotSearch;
import com.example.hotHub.service.BiliHotPointService;
import com.example.hotHub.utils.RestTemplateUtil;
import com.example.hotHub.utils.SimpleMap;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

@Slf4j
@Service
public class BiliHotPointServiceImpl implements BiliHotPointService {

    @Autowired
    private ExecutorService threadPoolExecutor;

    @Autowired
    private RestTemplateUtil restTemplateUtil;

    private String getVideoUrl(String bvid, String cid) {
        String target = "http://api.bilibili.com/x/player/playurl?bvid=" + bvid + "&cid=" + cid + "&qn=32&fnval=0&platform=html5";

        SimpleMap response = restTemplateUtil.doGet(target, null, null, SimpleMap.class);
        String videoUrl = response.getMap("data")
                .getList("durl", SimpleMap.class).get(0)
                .getString("url");

        return videoUrl;
    }

    @SneakyThrows
    @Override
    public List<NormalHotSearch> getHotPointList(String type) {
        String target = "https://api.bilibili.com/x/web-interface/ranking/v2?rid=0&type=" + type;

        List<NormalHotSearch> finalNormalHotSearchList = new CopyOnWriteArrayList<>();

        SimpleMap response = restTemplateUtil.doGet(target, null, null, SimpleMap.class);
        List<SimpleMap> list = response.getMap("data").getList("list", SimpleMap.class);

        int size = list.size();
        CountDownLatch latch = new CountDownLatch(size);

        long biliStart = System.currentTimeMillis();

        for (SimpleMap item : list) {

            threadPoolExecutor.execute(() -> {
               try {
                   String title = item.getString("title");
                   String url = item.getString("short_link");
                   String desc = item.getString("desc");
                   String imageUrl = item.getString("pic");
                   Integer hotValue = item.getMap("stat").getInt("view");
                   NormalHotSearch normalHotSearch = new NormalHotSearch()
                           .setTitle(title)
                           .setUrl(url)
                           .setDescribe(desc)
                           .setHotValue(hotValue)
                           .setImageUrl(imageUrl);
                   normalHotSearch = url2File(getVideoUrl(item.getString("bvid"), item.getString("cid")), "", normalHotSearch);

                   finalNormalHotSearchList.add(normalHotSearch);
               } catch (Exception ex) {

               } finally {
                   latch.countDown();
               }
           });
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        List<NormalHotSearch> normalHotSearchList = finalNormalHotSearchList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

        long biliEnd = System.currentTimeMillis();

        log.info("成功爬取BiliBili热点, 用时{}s", new BigDecimal(biliEnd - biliStart).divide(new BigDecimal(1000).setScale(2, BigDecimal.ROUND_HALF_UP)));

        return normalHotSearchList;
    }

    public NormalHotSearch url2File(String videoUrl, String preStr, NormalHotSearch normalHotSearch) {
        try {

            int bytesum = 0;
            int byteread = 0;

            URL url = new URL(videoUrl);
            URLConnection conn = url.openConnection();
            InputStream inStream = conn.getInputStream();

            String[] paths = url.getPath().split("/");
            String filePath = "/video/bili/" + preStr + paths[paths.length - 1];

            normalHotSearch.setVideoUrl(filePath);
            normalHotSearch.setVideoName(paths[paths.length - 1]);

            String path = CommonConst.USER_ROOT_HOME + filePath;

            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            if (!file.exists()) {
                file.createNewFile();
            } else {
                return normalHotSearch;
            }

            BufferedOutputStream fs = new BufferedOutputStream(new FileOutputStream(file));

            long startTime = System.currentTimeMillis();

            byte[] buffer = new byte[1024000];
            while ((byteread = inStream.read(buffer)) != -1) {
                bytesum += byteread;
//                System.out.println(bytesum);
                fs.write(buffer, 0, byteread);
            }

            long end = System.currentTimeMillis();

            log.info("爬取bili视频: {}, 视频大小: {}MB, 总用时: {}s", paths[paths.length - 1], new BigDecimal(file.length() * 1.0 / (1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP), (end - startTime) * 1.0 / 1000);

            return normalHotSearch;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}
